home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2001 May / SGI Freeware 2001 May - Disc 1.iso / dist / fw_mysql.idb / usr / freeware / share / sql-bench / server-cfg.z / server-cfg
Encoding:
Text File  |  1999-10-18  |  67.1 KB  |  2,414 lines

  1. #!/usr/bin/perl
  2. ####
  3. # The configuration file for the DBI/DBD tests on different databases ....
  4. # You will need the DBD module for the database you are running.
  5. # Monty made this bench script and I (Luuk de Boer) rewrote it to DBI/DBD.
  6. # Monty rewrote this again to use packages.
  7. #
  8. # Each database has a different package that has 3 functions:
  9. # new        Creates a object with some standard slot
  10. # version    Version number of the server
  11. # create    Generates commands to create a table
  12. #
  13.  
  14. #
  15. # First some global functions that help use the packages:
  16. #
  17.  
  18. sub get_server
  19. {
  20.   my ($name,$host,$database,$odbc)=@_;
  21.   my ($server);
  22.   if ($name =~ /mysql/i)
  23.   { $server=new db_MySQL($host, $database); }
  24.   elsif ($name =~ /pg/i)
  25.   { $server= new db_Pg($host,$database); }
  26.   elsif ($name =~ /msql/i)
  27.   { $server= new db_mSQL($host,$database); }
  28.   elsif ($name =~ /solid/i)
  29.   { $server= new db_Solid($host,$database); }
  30.   elsif ($name =~ /Empress/i)
  31.   { $server= new db_Empress($host,$database); }
  32.   elsif ($name =~ /Oracle/i)
  33.   { $server= new db_Oracle($host,$database); }
  34.   elsif ($name =~ /Access/i)
  35.   { $server= new db_access($host,$database); }
  36.   elsif ($name =~ /Informix/i)
  37.   { $server= new db_Informix($host,$database); }
  38.   elsif ($name =~ /ms-sql/i)
  39.   { $server= new db_ms_sql($host,$database); }
  40.   elsif ($name =~ /sybase/i)
  41.   { $server= new db_sybase($host,$database); }
  42.   elsif ($name =~ /Adabas/i)            # Adabas has two drivers
  43.   {
  44.     $server= new db_Adabas($host,$database);
  45.     if ($name =~ /AdabasD/i)
  46.     {
  47.       $server->{'data_source'} =~ s/:Adabas:/:AdabasD:/;
  48.     }
  49.   }
  50.   elsif ($name =~ /DB2/i)
  51.   { $server= new db_db2($host,$database); }
  52.   else
  53.   {
  54.       die "Unknown sql server name used: $name\nUse one of: Access, Adabas, AdabasD, Empress, Oracle, Informix, DB2, mSQL, MS-SQL, MySQL, Pg, Solid or Sybase.\nIf the connection is done trough ODBC the name must end with _ODBC\n";
  55.   }
  56.   if ($name =~ /_ODBC$/i || defined($odbc) && $odbc)
  57.   {
  58.     if (! ($server->{'data_source'} =~ /^([^:]*):([^:]+):([^:]*)/ ))
  59.     {
  60.       die "Can't find databasename in data_source: '" .
  61.       $server->{'data_source'}. "'\n";
  62.     }
  63.     if ($3) {
  64.       $server->{'data_source'} = "$1:ODBC:$3";
  65.     } else {
  66.       $server->{'data_source'} = "$1:ODBC:$database";
  67.     }
  68.   }
  69.   return $server;
  70. }
  71.  
  72. sub all_servers
  73. {
  74.   return ["Access", "Adabas", "DB2", "Empress", "Oracle", "Informix", "mSQL",
  75.       "MS-SQL", "MySQL", "Pg", "Solid", "Sybase"];
  76. }
  77.  
  78. #############################################################################
  79. #         First the configuration for MySQL off course :-)
  80. #############################################################################
  81.  
  82. package db_MySQL;
  83.  
  84. sub new
  85. {
  86.   my ($type,$host,$database)= @_;
  87.   my $self= {};
  88.   my %limits;
  89.   bless $self;
  90.  
  91.   $self->{'cmp_name'}        = "mysql";
  92.   $self->{'data_source'}    = "DBI:mysql:$database:$host";
  93.   $self->{'limits'}        = \%limits;
  94.   $self->{'smds'}        = \%smds;
  95.   $self->{'blob'}        = "blob";
  96.   $self->{'text'}        = "text";
  97.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  98.  
  99.   $limits{'max_conditions'}    = 9999; # (Actually not a limit)
  100.   $limits{'max_columns'}    = 2000;    # Max number of columns in table
  101.   $limits{'max_text_size'}    = 65000; # Max size with default buffers.
  102.   $limits{'query_size'}        = 1000000; # Max size with default buffers.
  103.   $limits{'max_index'}        = 16; # Max number of keys
  104.   $limits{'max_index_parts'}    = 16; # Max segments/key
  105.   $limits{'max_column_name'}    = 64; # max table and column name
  106.  
  107.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  108.   $limits{'load_data_infile'}    = 1; # Has load data infile
  109.   $limits{'lock_tables'}    = 1; # Has lock tables
  110.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  111.   $limits{'group_functions'}    = 1; # Have group functions
  112.   $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
  113.   $limits{'select_without_from'}= 1; # Can do 'select 1';
  114.   $limits{'multi_drop'}        = 1; # Drop table can take many tables
  115.   $limits{'subqueries'}        = 0; # Doesn't support sub-queries.
  116.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  117.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  118.   $limits{'having_with_alias'}  = 1; # Can use aliases in HAVING
  119.   $limits{'having_with_group'}    = 0; # Can't use group functions in HAVING
  120.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  121.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  122.   $limits{'group_by_position'}  = 1; # Can use 'GROUP BY 1'
  123.   $limits{'alter_table'}    = 1; # Have ALTER TABLE
  124.   $limits{'alter_add_multi_col'}= 1; #Have ALTER TABLE t add a int,add b int;
  125.   $limits{'alter_table_dropcol'}= 1; # Have ALTER TABLE DROP column
  126.   $limits{'multi_value_insert'} = 1; # Have INSERT ... values (1,2),(3,4)
  127.  
  128.   $limits{'group_func_extra_std'} = 1; # Have group function std().
  129.  
  130.   $limits{'func_odbc_mod'}    = 1; # Have function mod.
  131.   $limits{'func_extra_%'}    = 1; # Has % as alias for mod()
  132.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  133.   $limits{'func_extra_if'}    = 1; # Have function if.
  134.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  135.   $limits{'NEG'}        = 1; # Supports -id
  136.   $limits{'func_extra_in_num'}    = 1; # Has function in
  137.   $limits{'limit'}        = 1;        # supports the limit attribute
  138.  
  139.   $smds{'time'}            = 1;
  140.   $smds{'q1'}     = 'b';        # with time not supp by mysql ('')
  141.   $smds{'q2'}     = 'b';
  142.   $smds{'q3'}     = 'b';        # with time ('')
  143.   $smds{'q4'}     = 'c';        # with time not supp by mysql (d)
  144.   $smds{'q5'}     = 'b';        # with time not supp by mysql ('')
  145.   $smds{'q6'}     = 'c';        # with time not supp by mysql ('')
  146.   $smds{'q7'}     = 'c';
  147.   $smds{'q8'}     = 'f';
  148.   $smds{'q9'}     = 'c';
  149.   $smds{'q10'}     = 'b';
  150.   $smds{'q11'}     = 'b';
  151.   $smds{'q12'}     = 'd';
  152.   $smds{'q13'}     = 'c';
  153.   $smds{'q14'}     = 'd';
  154.   $smds{'q15'}     = 'd';
  155.   $smds{'q16'}     = 'a';
  156.   $smds{'q17'}     = 'c';
  157.  
  158.   return $self;
  159. }
  160.  
  161. #
  162. # Get the version number of the database
  163. #
  164.  
  165. sub version
  166. {
  167.   my ($self)=@_;
  168.   my ($dbh,$sth,$version,@row);
  169.  
  170.   $dbh=$self->connect();
  171.   $sth = $dbh->prepare("select VERSION()") or die $DBI::errstr;
  172.   $version="MySQL 3.20.?";
  173.   if ($sth->execute && (@row = $sth->fetchrow_array))
  174.   {
  175.     $row[0] =~ s/-/ /g;            # To get better tables with long names
  176.     $version="MySQL $row[0]";
  177.   }
  178.   $sth->finish;
  179.   $dbh->disconnect;
  180.   return $version;
  181. }
  182.  
  183. #
  184. # Connection with optional disabling of logging
  185. #
  186.  
  187. sub connect
  188. {
  189.   my ($self)=@_;
  190.   my ($dbh);
  191.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  192.             $main::opt_password,{ PrintError => 0}) ||
  193.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  194.  
  195.   $dbh->do("SET OPTION LOG_OFF=1,UPDATE_LOG=0");
  196.   return $dbh;
  197. }
  198.  
  199. #
  200. # Returns a list of statements to create a table
  201. # The field types are in ANSI SQL format.
  202. #
  203. # If one uses $main::opt_fast then one is allowed to use
  204. # non standard types to get better speed.
  205. #
  206.  
  207. sub create
  208. {
  209.   my($self,$table_name,$fields,$index) = @_;
  210.   my($query,@queries);
  211.  
  212.   $query="create table $table_name (";
  213.   foreach $field (@$fields)
  214.   {
  215.     $field =~ s/ decimal/ double(10,2)/i;
  216.     $field =~ s/ big_decimal/ double(10,2)/i;
  217.     $field =~ s/ date/ int/i;        # Because of tcp ?
  218.     $query.= $field . ',';
  219.   }
  220.   foreach $index (@$index)
  221.   {
  222.     $query.= $index . ',';
  223.   }
  224.   substr($query,-1)=")";        # Remove last ',';
  225.   push(@queries,$query);
  226.   return @queries;
  227. }
  228.  
  229. sub insert_file {
  230.   my ($self,$dbname, $file, $dbh) = @_;
  231.   my ($command, $sth);
  232.  
  233.   $file =~ s|\\|/|g;            # Change Win32 names to Unix syntax
  234.   $command = "load data infile '$file' into table $dbname columns optionally enclosed by '\\'' terminated by ','";
  235. #  print "$command\n";
  236.   $sth = $dbh->do($command) or die $DBI::errstr;
  237.   return $sth;            # Contains number of rows
  238. }
  239.  
  240. #
  241. # Do any conversions to the ANSI SQL query so that the database can handle it
  242. #
  243.  
  244. sub query {
  245.   my($self,$sql) = @_;
  246.   return $sql;
  247. }
  248.  
  249. sub drop_index {
  250.   my ($self,$table,$index) = @_;
  251.   return "DROP INDEX $index ON $table";
  252. }
  253.  
  254. #
  255. # Abort if the server has crashed
  256. # return: 0 if ok
  257. #      1 question should be retried
  258. #
  259.  
  260. sub abort_if_fatal_error
  261. {
  262.   return 0;
  263. }
  264.  
  265.  
  266. #############################################################################
  267. #             Definitions for mSQL
  268. #############################################################################
  269.  
  270. package db_mSQL;
  271.  
  272. sub new
  273. {
  274.   my ($type,$host,$database)= @_;
  275.   my $self= {};
  276.   my %limits;
  277.   bless $self;
  278.  
  279.   $self->{'cmp_name'}        = "msql";
  280.   $self->{'data_source'}    = "DBI:mSQL:$database:$main::$opt_host";
  281.   $self->{'limits'}        = \%limits;
  282.   $self->{'double_quotes'}    = 0;
  283.  
  284.   $limits{'max_conditions'}    = 74;
  285.   $limits{'max_columns'}    = 75;
  286.   $limits{'max_text_size'}    = 32000;
  287.   $limits{'query_size'}        = 65535;
  288.   $limits{'max_index'}        = 5;
  289.   $limits{'max_index_parts'}    = 10;
  290.   $limits{'max_column_name'} = 35;
  291.  
  292.   $limits{'join_optimizer'}    = 0;        # Can't optimize FROM tables
  293.   $limits{'load_data_infile'}    = 0;
  294.   $limits{'lock_tables'}    = 0;
  295.   $limits{'functions'}        = 0;
  296.   $limits{'group_functions'}    = 0;
  297.   $limits{'multi_drop'}        = 0;
  298.   $limits{'select_without_from'}= 0;
  299.   $limits{'subqueries'}        = 0;
  300.   $limits{'left_outer_join'}    = 0;
  301.   $limits{'table_wildcard'}    = 0;
  302.   $limits{'having_with_alias'}  = 0;
  303.   $limits{'having_with_group'}    = 0;
  304.   $limits{'like_with_column'}    = 1;
  305.   $limits{'order_by_position'}  = 1;
  306.   $limits{'group_by_position'}  = 1;
  307.   $limits{'alter_table'}    = 0;
  308.   $limits{'alter_add_multi_col'}= 0;
  309.   $limits{'alter_table_dropcol'}= 0;
  310.   $limits{'group_func_extra_std'} = 0;
  311.   $limits{'limit'}        = 1;        # supports the limit attribute
  312.  
  313.   $limits{'func_odbc_mod'}    = 0;
  314.   $limits{'func_extra_%'}    = 0;
  315.   $limits{'func_odbc_floor'}    = 0;
  316.   $limits{'func_extra_if'}    = 0;
  317.   $limits{'column_alias'}    = 0;
  318.   $limits{'NEG'}        = 0;
  319.   $limits{'func_extra_in_num'}    = 0;
  320.  
  321.   $self->{'blob'}        = "text(" . $limits{'max_text_size'} .")";
  322.   $self->{'text'}        = "text(" . $limits{'max_text_size'} .")";
  323.   return $self;
  324. }
  325.  
  326. #
  327. # Get the version number of the database
  328. #
  329.  
  330. sub version
  331. {
  332.   my ($tmp,$dir);
  333.   foreach $dir ("/usr/local/Hughes", "/usr/local/mSQL","/my/local/mSQL",
  334.         "/usr/local")
  335.   {
  336.     if (-x "$dir/bin/msqladmin")
  337.     {
  338.       $tmp=`$dir/bin/msqladmin version | grep server`;
  339.       if ($tmp =~ /^\s*(.*\w)\s*$/)
  340.       {                # Strip pre- and endspace
  341.     $tmp=$1;
  342.     $tmp =~ s/\s+/ /g;    # Remove unnecessary spaces
  343.     return $tmp;
  344.       }
  345.     }
  346.   }
  347.   return "mSQL version ???";
  348. }
  349.  
  350.  
  351. sub connect
  352. {
  353.   my ($self)=@_;
  354.   my ($dbh);
  355.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  356.             $main::opt_password,{ PrintError => 0}) ||
  357.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  358.   return $dbh;
  359. }
  360.  
  361. #
  362. # Can't handle many field types, so we map everything to int and real.
  363. #
  364.  
  365. sub create
  366. {
  367.   my($self,$table_name,$fields,$index) = @_;
  368.   my($query,@queries,$name,$nr);
  369.  
  370.   $query="create table $table_name (";
  371.   foreach $field (@$fields)
  372.   {
  373.     $field =~ s/varchar/char/i;        # mSQL doesn't have VARCHAR()
  374.     # mSQL can't handle more than the real basic int types
  375.     $field =~ s/tinyint|smallint|mediumint|integer/int/i;
  376.     # mSQL can't handle different visual lengths
  377.     $field =~ s/int\(\d*\)/int/i;
  378.     # mSQL dosen't have float, change it to real
  379.     $field =~ s/float(\(\d*,\d*\)){0,1}/real/i;
  380.     $field =~ s/double(\(\d*,\d*\)){0,1}/real/i;
  381.     # mSQL doesn't have blob, it has text instead
  382.     if ($field =~ / blob/i)
  383.     {
  384.       $name=$self->{'blob'};
  385.       $field =~ s/ blob/ $name/;
  386.     }
  387.     $query.= $field . ',';
  388.   }
  389.   substr($query,-1)=")";        # Remove last ',';
  390.   push(@queries,$query);
  391.   $nr=0;
  392.  
  393.   # Prepend table_name to index name because the the name may clash with
  394.   # a field name. (Should be diffent name space, but this is mSQL...)
  395.  
  396.   foreach $index (@$index)
  397.   {
  398.     # Primary key is unique index in mSQL
  399.     $index =~ s/primary key/unique index primary/i;
  400.     if ($index =~ /^unique\s*\(([^\(]*)\)$/i)
  401.     {
  402.       $nr++;
  403.       push(@queries,"create unique index ${table_name}_$nr on $table_name ($1)");
  404.     }
  405.     else
  406.     {
  407.       if (!($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i))
  408.       {
  409.     die "Can't parse index information in '$index'\n";
  410.       }
  411.       push(@queries,"create $1 ${table_name}_$2 on $table_name $3");
  412.     }
  413.   }
  414.   return @queries;
  415. }
  416.  
  417.  
  418. sub insert_file {
  419.   my($self,$dbname, $file) = @_;
  420.   print "insert an ascii file isn't supported by mSQL\n";
  421.   return 0;
  422. }
  423.  
  424.  
  425. sub query {
  426.   my($self,$sql) = @_;
  427.   return $sql;
  428. }
  429.  
  430. sub drop_index
  431. {
  432.   my ($self,$table,$index) = @_;
  433.   return "DROP INDEX $index FROM $table";
  434. }
  435.  
  436. sub abort_if_fatal_error
  437. {
  438.   return 0;
  439. }
  440.  
  441. #############################################################################
  442. #             Definitions for PostgreSQL                    #
  443. #############################################################################
  444.  
  445. package db_Pg;
  446.  
  447. sub new
  448. {
  449.   my ($type,$host,$database)= @_;
  450.   my $self= {};
  451.   my %limits;
  452.   bless $self;
  453.  
  454.   $self->{'cmp_name'}        = "pg";
  455.   $self->{'data_source'}    = "DBI:Pg:dbname=$database";
  456.   $self->{'limits'}        = \%limits;
  457.   $self->{'smds'}        = \%smds;
  458.   $self->{'blob'}        = "text";
  459.   $self->{'text'}        = "text";
  460.   $self->{'double_quotes'}    = 1;
  461.  
  462.   $limits{'max_conditions'}    = 9;        # This makes Pg real slow
  463.   $limits{'max_columns'}    = 300;        # 500 crashes pg 6.3
  464.   $limits{'max_text_size'}    = 7000;        # 8000 crashes pg 6.3
  465.   $limits{'query_size'}        = 8191;
  466.   $limits{'max_index'}        = 7;        # Is this true ?
  467.   $limits{'max_index_parts'}    = 16;        # Is this true ?
  468.   $limits{'max_column_name'} = 32;        # Is this true
  469.  
  470.   $limits{'join_optimizer'}    = 1;        # Can't optimize FROM tables
  471.   $limits{'load_data_infile'}    = 0;        # Is this true ?
  472.   $limits{'lock_tables'}    = 0;        # Is this true ?
  473.   $limits{'functions'}        = 1;
  474.   $limits{'group_functions'}    = 1;
  475.   $limits{'group_func_sql_min_str'}    = 0; # Can execute MIN() and MAX() on strings
  476.   $limits{'multi_drop'}        = 1;
  477.   $limits{'select_without_from'}= 1;
  478.   $limits{'subqueries'}        = 1;
  479.   $limits{'left_outer_join'}    = 0;
  480.   $limits{'table_wildcard'}    = 1;
  481.   $limits{'having_with_alias'}  = 0;
  482.   $limits{'having_with_group'}    = 0;
  483.   $limits{'like_with_column'}    = 0;
  484.   $limits{'order_by_position'}  = 1;
  485.   $limits{'group_by_position'}  = 1;
  486.   $limits{'alter_table'}    = 1;
  487.   $limits{'alter_add_multi_col'}= 0;
  488.   $limits{'alter_table_dropcol'}= 0;
  489.  
  490.   $limits{'group_func_extra_std'} = 0;
  491.  
  492.   $limits{'func_odbc_mod'}    = 2;        # Has %
  493.   $limits{'func_extra_%'}    = 1;
  494.   $limits{'func_odbc_floor'}    = 0;
  495.   $limits{'func_extra_if'}    = 0;
  496.   $limits{'column_alias'}    = 1;
  497.   $limits{'NEG'}        = 0;        # Can't handle -id
  498.   $limits{'func_extra_in_num'}    = 1;
  499.  
  500.   # the different cases per query ...
  501.   $smds{'q1'}     = 'b'; # with time
  502.   $smds{'q2'}     = 'b';
  503.   $smds{'q3'}     = 'b'; # with time
  504.   $smds{'q4'}     = 'c'; # with time
  505.   $smds{'q5'}     = 'b'; # with time
  506.   $smds{'q6'}     = 'c'; # strange error ....
  507.   $smds{'q7'}     = 'c';
  508.   $smds{'q8'}     = 'f'; # needs 128M to execute - can't do insert ...group by
  509.   $smds{'q9'}     = 'c';
  510.   $smds{'q10'}     = 'b';
  511.   $smds{'q11'}     = 'b'; # can't do float8 * int4 - create operator
  512.   $smds{'q12'}     = 'd'; # strange error???
  513.   $smds{'q13'}     = 'c';
  514.   $smds{'q14'}     = 'd'; # strange error???
  515.   $smds{'q15'}     = 'd'; # strange error???
  516.   $smds{'q16'}     = 'a';
  517.   $smds{'q17'}     = 'c';
  518.   $smds{'time'} = 1;    # the use of the time table -> 1 is on.
  519.             # when 0 then the date field must be a
  520.             # date field not a int field!!!
  521.   return $self;
  522. }
  523.  
  524. # couldn't find the option to get the version number
  525.  
  526. sub version
  527. {
  528.   my ($version,$dir);
  529.   foreach $dir ($ENV{'PGDATA'},"/usr/local/pgsql/data", "/my/local/pgsql/")
  530.   {
  531.     if ($dir && -e "$dir/PG_VERSION")
  532.     {
  533.       $version= `cat $dir/PG_VERSION`;
  534.       if ($? == 0)
  535.       {
  536.     chomp($version);
  537.     return "PostgreSQL $version";
  538.       }
  539.     }
  540.   }
  541.   return "PostgreSQL version ???";
  542. }
  543.  
  544.  
  545. sub connect
  546. {
  547.   my ($self)=@_;
  548.   my ($dbh);
  549.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  550.             $main::opt_password,{ PrintError => 0}) ||
  551.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  552.   return $dbh;
  553. }
  554.  
  555.  
  556. sub create
  557. {
  558.   my($self,$table_name,$fields,$index) = @_;
  559.   my($query,@queries,$name,$in,$indfield,$table,$nr);
  560.  
  561.   $query="create table $table_name (";
  562.   foreach $field (@$fields)
  563.   {
  564.     if ($main::opt_fast)
  565.     {
  566.       # Allow use of char2, char4, char8 or char16
  567.       $field =~ s/char(2|4|8|16)/char$1/;
  568.     }
  569.     # Pg can't handle more than the real basic int types
  570.     $field =~ s/tinyint|smallint|mediumint|integer/int/;
  571.     # Pg can't handle different visual lengths
  572.     $field =~ s/int\(\d*\)/int/;
  573.     $field =~ s/float\(\d*,\d*\)/float/;
  574.     $field =~ s/ double/ float/;
  575.     $field =~ s/ decimal/ float/i;
  576.     $field =~ s/ big_decimal/ float/i;
  577.     $field =~ s/ date/ int/i;
  578.     # Pg doesn't have blob, it has text instead
  579.     $field =~ s/ blob/ text/;
  580.     $query.= $field . ',';
  581.   }
  582.   substr($query,-1)=")";        # Remove last ',';
  583.   push(@queries,$query);
  584.   foreach $index (@$index)
  585.   {
  586.     $index =~ s/primary key/unique index primary_key/i;
  587.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  588.     {
  589.       $indfield="using btree (" .$1.")";
  590.       $in="unique index";
  591.       $table="index_$nr"; $nr++;
  592.     }
  593.     elsif ($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i)
  594.     {
  595.       $indfield="using btree " .$3;
  596.       $in="index";
  597.       $table="index_$nr"; $nr++;
  598.     }
  599.     else
  600.     {
  601.       die "Can't parse index information in '$index'\n";
  602.     }
  603.     push(@queries,"create $in ${table_name}_$table on $table_name $indfield");
  604.   }
  605.   $queries[0]=$query;
  606.   return @queries;
  607. }
  608.  
  609. sub insert_file {
  610.   my ($self,$dbname, $file, $dbh) = @_;
  611.   my ($command, $sth);
  612.  
  613. # Syntax:
  614. # copy [binary] <class_name> [with oids]
  615. #      {to|from} {<filename>|stdin|stdout} [using delimiters <delim>]
  616.   print "The ascii files aren't correct for postgres ....!!!\n";
  617.   $command = "copy $dbname from '$file' using delimiters ','";
  618.   print "$command\n";
  619.   $sth = $dbh->do($command) or die $DBI::errstr;
  620.   return $sth;
  621. }
  622.  
  623. #
  624. # As postgreSQL wants A % B instead of standard mod(A,B) we have to map
  625. # This will not handle all cases, but as the benchmarks doesn't use functions
  626. # inside MOD() the following should work
  627. #
  628. # PostgreSQL cant handle count(*) or even count(1), but it can handle
  629. # count(1+1) sometimes. ==> this is solved in PostgreSQL 6.3
  630. #
  631.  
  632. sub query {
  633.   my($self,$sql) = @_;
  634.   my(@select,$change);
  635.   $sql =~ s/mod\(([^,]*),([^\)]*)\)/\($1 % $2\)/gi;
  636. # if you use PostgreSQL 6.1.x uncomment the lines below
  637. #  if ($sql =~ /select\s+count\(\*\)\s+from/i) {
  638. #  }
  639. #  elsif ($sql =~ /count\(\*\)/i)
  640. #  {
  641. #    if ($sql =~ /select\s+(.*)\s+from/i)
  642. #    {
  643. #      @select = split(/,/,$1);
  644. #      if ($select[0] =~ /(.*)\s+as\s+\w+$/i)
  645. #      {
  646. #     $change = $1;
  647. #      }
  648. #      else
  649. #      {
  650. #    $change = $select[0];
  651. #      }
  652. #    }
  653. #    if (($change =~ /count/i) || ($change eq "")) {
  654. #      $change = "1+1";
  655. #    }
  656. #    $sql =~ s/count\(\*\)/count($change)/gi;
  657. #  }
  658. # till here.
  659.   return $sql;
  660. }
  661.  
  662. sub drop_index
  663. {
  664.   my ($self,$table,$index) = @_;
  665.   return "DROP INDEX $index";
  666. }
  667.  
  668. sub abort_if_fatal_error
  669. {
  670.   return 1 if ($DBI::errstr =~ /sent to backend, but backend closed/i);
  671.   return 0;
  672. }
  673.  
  674.  
  675. sub vacuum
  676. {
  677.   my ($self,$dbh)=@_;
  678.   my ($loop_time,$end_time);
  679.   $loop_time=new Benchmark;
  680.   $dbh->do("vacuum") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
  681.   $end_time=new Benchmark;
  682.   print "Time for book-keeping (1): " .
  683.   Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"noc") . "\n\n";
  684. }
  685.  
  686.  
  687. #############################################################################
  688. #             Definitions for Solid
  689. #############################################################################
  690.  
  691. package db_Solid;
  692.  
  693. sub new
  694. {
  695.   my ($type,$host,$database)= @_;
  696.   my $self= {};
  697.   my %limits;
  698.   bless $self;
  699.  
  700.   $self->{'cmp_name'}        = "solid";
  701.   $self->{'data_source'}    = "DBI:Solid:";
  702.   $self->{'limits'}        = \%limits;
  703.   $self->{'smds'}        = \%smds;
  704.   $self->{'blob'}        = "long varchar";
  705.   $self->{'text'}        = "long varchar";
  706.   $self->{'double_quotes'}    = 1;
  707.  
  708.   $limits{'max_conditions'}    = 9999;        # Probably big enough
  709.   $limits{'max_columns'}    = 2000;        # From crash-me
  710.   $limits{'max_text_size'}    = 65492;    # According to tests
  711.   $limits{'query_size'}        = 65535;    # Probably a limit
  712.   $limits{'max_index'}        = 64;        # Probably big enough
  713.   $limits{'max_index_parts'}    = 64;
  714.   $limits{'max_column_name'} = 80;
  715.  
  716.   $limits{'join_optimizer'}    = 1;
  717.   $limits{'load_data_infile'}    = 0;
  718.   $limits{'lock_tables'}    = 0;
  719.   $limits{'functions'}        = 1;
  720.   $limits{'group_functions'}    = 1;
  721.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  722.   $limits{'select_without_from'}= 0;        # Can do 'select 1' ?;
  723.   $limits{'multi_drop'}        = 0;
  724.   $limits{'subqueries'}        = 1;
  725.   $limits{'left_outer_join'}    = 1;
  726.   $limits{'table_wildcard'}    = 1;
  727.   $limits{'having_with_alias'}  = 0;
  728.   $limits{'having_with_group'}    = 1;
  729.   $limits{'like_with_column'}    = 1;
  730.   $limits{'order_by_position'}  = 0;        # 2.30.0018 can this
  731.   $limits{'group_by_position'}  = 0;
  732.   $limits{'alter_table'}    = 1;
  733.   $limits{'alter_add_multi_col'}= 0;
  734.   $limits{'alter_table_dropcol'}= 0;
  735.  
  736.   $limits{'group_func_extra_std'}    = 0;    # Have group function std().
  737.  
  738.   $limits{'func_odbc_mod'}    = 1;
  739.   $limits{'func_extra_%'}    = 0;
  740.   $limits{'func_odbc_floor'}    = 1;
  741.   $limits{'column_alias'}    = 1;
  742.   $limits{'NEG'}        = 1;
  743.   $limits{'func_extra_in_num'}    = 1;
  744.  
  745.   # for the smds small benchmark test ....
  746.   # the different cases per query ...
  747.   $smds{'q1'}     = 'a';
  748.   $smds{'q2'}     = '';
  749.   $smds{'q3'}     = 'b'; #doesn't work -> strange error about column -fixed
  750.   $smds{'q4'}     = 'a';
  751.   $smds{'q5'}     = 'b';
  752.   $smds{'q6'}     = 'c';
  753.   $smds{'q7'}     = 'b';
  754.   $smds{'q8'}     = 'f';
  755.   $smds{'q9'}     = 'b';
  756.   $smds{'q10'}     = 'b';
  757.   $smds{'q11'}     = '';
  758.   $smds{'q12'}     = 'd';
  759.   $smds{'q13'}     = 'b';
  760.   $smds{'q14'}     = 'd';
  761.   $smds{'q15'}     = 'd';
  762.   $smds{'q16'}     = '';
  763.   $smds{'q17'}     = '';
  764.   $smds{'time'} = 1;    # the use of the time table -> 1 is on.
  765.             # when 0 then the date field must be a
  766.             # date field not a int field!!!
  767.   return $self;
  768. }
  769.  
  770. #
  771. # Get the version number of the database
  772. #
  773.  
  774. sub version
  775. {
  776.   my ($version,$dir);
  777.   foreach $dir ($ENV{'SOLIDDIR'},"/usr/local/solid", "/my/local/solid")
  778.   {
  779.     if ($dir && -e "$dir/bin/solcon")
  780.     {
  781.       $version=`$dir/bin/solcon -e"ver" $main::opt_user $main::opt_password | grep Server | head -1`;
  782.       if ($? == 0)
  783.       {
  784.     chomp($version);
  785.     return $version;
  786.       }
  787.     }
  788.   }
  789.   return "Solid version ???";
  790. }
  791.  
  792. sub connect
  793. {
  794.   my ($self)=@_;
  795.   my ($dbh);
  796.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  797.             $main::opt_password,{ PrintError => 0}) ||
  798.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  799.   return $dbh;
  800. }
  801.  
  802. #
  803. # Returns a list of statements to create a table
  804. # The field types are in ANSI SQL format.
  805. #
  806.  
  807. sub create
  808. {
  809.   my($self,$table_name,$fields,$index) = @_;
  810.   my($query,@queries,$nr);
  811.  
  812.   $query="create table $table_name (";
  813.   foreach $field (@$fields)
  814.   {
  815.     $field =~ s/mediumint/integer/i;
  816.     $field =~ s/ double/ float/i;
  817.     # Solid doesn't have blob, it has long varchar
  818.     $field =~ s/ blob/ long varchar/;
  819.     $field =~ s/ decimal/ float/i;
  820.     $field =~ s/ big_decimal/ float/i;
  821.     $field =~ s/ date/ int/i;
  822.     $query.= $field . ',';
  823.   }
  824.   substr($query,-1)=")";        # Remove last ',';
  825.   push(@queries,$query);
  826.   $nr=0;
  827.   foreach $index (@$index)
  828.   {
  829.     if ($index =~ /^primary key/i || $index =~ /^unique/i)
  830.     {                    # Add to create statement
  831.       substr($queries[0],-1,0)="," . $index;
  832.     }
  833.     else
  834.     {
  835.       $index =~ /^(.*)\s+(\(.*\))$/;
  836.       push(@queries,"create ${1}$nr on $table_name $2");
  837.       $nr++;
  838.     }
  839.   }
  840.   return @queries;
  841. }
  842.  
  843. # there is no sql statement in solid which can do the load from
  844. # an ascii file in the db ... but there is the speedloader program
  845. # an external program which can load the ascii file in the db ...
  846. # the server must be down before using speedloader !!!!
  847. # (in the standalone version)
  848. # it works also with a control file ... that one must be made ....
  849. sub insert_file {
  850.   my ($self, $dbname, $file) = @_;
  851.   my ($speedcmd);
  852.   $speedcmd = '/usr/local/solid/bin/solload';
  853.   print "At this moment not supported - solid server must go down \n";
  854.   return 0;
  855. }
  856.  
  857. # solid can't handle an alias in a having statement so
  858. # select test as foo from tmp group by foo having foor > 2
  859. # becomes
  860. # select test as foo from tmp group by foo having test > 2
  861. #
  862. sub query {
  863.   my($self,$sql) = @_;
  864.   my(@select,$tmp,$newhaving,$key,%change);
  865.  
  866.   if ($sql =~ /having\s+/i)
  867.   {
  868.     if ($sql =~ /select (.*) from/i)
  869.     {
  870.       (@select) = split(/,\s*/, $1);
  871.       foreach $tmp (@select)
  872.       {
  873.     if ($tmp =~ /(.*)\s+as\s+(\w+)/)
  874.     {
  875.       $change{$2} = $1;
  876.     }
  877.       }
  878.     }
  879.     if ($sql =~ /having\s+(\w+)/i)
  880.     {
  881.       $newhaving = $1;
  882.       foreach $key (sort {$a cmp $b} keys %change)
  883.       {
  884.     if ($newhaving eq $key)
  885.     {
  886.       $newhaving =~ s/$key/$change{$key}/g;
  887.     }
  888.       }
  889.     }
  890.     $sql =~ s/(having)\s+(\w+)/$1 $newhaving/i;
  891.   }
  892.   return $sql;
  893. }
  894.  
  895.  
  896. sub drop_index
  897. {
  898.   my ($self,$table,$index) = @_;
  899.   return "DROP INDEX $index";
  900. }
  901.  
  902. sub abort_if_fatal_error
  903. {
  904.   return 0;
  905. }
  906.  
  907. #############################################################################
  908. #             Definitions for Empress
  909. #
  910. # at this moment DBI:Empress can only handle 200 prepare statements ...
  911. # so Empress can't be tested with the benchmark test :(
  912. #############################################################################
  913.  
  914. package db_Empress;
  915.  
  916. sub new
  917. {
  918.   my ($type,$host,$database)= @_;
  919.   my $self= {};
  920.   my %limits;
  921.   bless $self;
  922.  
  923.   $self->{'cmp_name'}        = "empress";
  924.   $self->{'data_source'}        = "DBI:EmpressNet:SERVER=$main::$opt_host;Database=/usr/local/empress/rdbms/bin/$database";
  925.   $self->{'limits'}        = \%limits;
  926.   $self->{'smds'}        = \%smds;
  927.   $self->{'blob'}        = "text";
  928.   $self->{'text'}        = "text";
  929.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  930.  
  931.   $limits{'max_conditions'}    = 1258;
  932.   $limits{'max_columns'}    = 226;        # server is disconnecting????
  933.             # above this value .... but can handle 2419 columns
  934.             # maybe something for crash-me ... but how to check ????
  935.   $limits{'max_text_size'}    = 4095;        # max returned ....
  936.   $limits{'query_size'}        = 65535;    # Not a limit, big enough
  937.   $limits{'max_index'}        = 64;        # Big enough
  938.   $limits{'max_index_parts'}    = 64;        # Big enough
  939.   $limits{'max_column_name'}     = 31;
  940.  
  941.   $limits{'join_optimizer'}    = 1;
  942.   $limits{'load_data_infile'}    = 0;
  943.   $limits{'lock_tables'}    = 1;
  944.   $limits{'functions'}        = 1;
  945.   $limits{'group_functions'}    = 1;
  946.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  947.   $limits{'select_without_from'}= 0;
  948.   $limits{'multi_drop'}        = 0;
  949.   $limits{'subqueries'}        = 1;
  950.   $limits{'table_wildcard'}    = 0;
  951.   $limits{'having_with_alias'}  = 0;     # AS isn't supported in a select
  952.   $limits{'having_with_group'}    = 1;
  953.   $limits{'like_with_column'}    = 1;
  954.   $limits{'order_by_position'}  = 1;
  955.   $limits{'group_by_position'}  = 0;
  956.   $limits{'alter_table'}    = 1;
  957.   $limits{'alter_add_multi_col'}= 0;
  958.   $limits{'alter_table_dropcol'}= 0;
  959.  
  960.   $limits{'group_func_extra_std'}= 0;    # Have group function std().
  961.  
  962.   $limits{'func_odbc_mod'}    = 0;
  963.   $limits{'func_extra_%'}    = 1;
  964.   $limits{'func_odbc_floor'}    = 1;
  965.   $limits{'func_extra_if'}    = 0;
  966.   $limits{'column_alias'}    = 0;
  967.   $limits{'NEG'}        = 1;
  968.   $limits{'func_extra_in_num'}    = 0;
  969.  
  970.   # for the smds small benchmark test ....
  971.   # the different cases per query ... EMPRESS
  972.   $smds{'q1'}     = 'a';
  973.   $smds{'q2'}     = '';
  974.   $smds{'q3'}     = 'a';
  975.   $smds{'q4'}     = 'a';
  976.   $smds{'q5'}     = 'a';
  977.   $smds{'q6'}     = 'a';
  978.   $smds{'q7'}     = 'b';
  979.   $smds{'q8'}     = 'd';
  980.   $smds{'q9'}     = 'b';
  981.   $smds{'q10'}     = 'a';
  982.   $smds{'q11'}     = '';
  983.   $smds{'q12'}     = 'd';
  984.   $smds{'q13'}     = 'b';
  985.   $smds{'q14'}     = 'b';
  986.   $smds{'q15'}     = 'a';
  987.   $smds{'q16'}     = '';
  988.   $smds{'q17'}     = '';
  989.   $smds{'time'} = 1;    # the use of the time table -> 1 is on.
  990.             # when 0 then the date field must be a
  991.             # date field not a int field!!!
  992.   return $self;
  993. }
  994.  
  995. #
  996. # Get the version number of the database
  997. #
  998.  
  999. sub version
  1000. {
  1001.   my ($self,$dbh)=@_;
  1002.   my ($version);
  1003.   $version="";
  1004.   if (-x "/usr/local/empress/rdbms/bin/empvers")
  1005.   {
  1006.     $version=`/usr/local/empress/rdbms/bin/empvers | grep Version`;
  1007.   }
  1008.   if ($version)
  1009.   {
  1010.     chomp($version);
  1011.   }
  1012.   else
  1013.   {
  1014.     $version="Empress version ???";
  1015.   }
  1016.   return $version;
  1017. }
  1018.  
  1019. sub connect
  1020. {
  1021.   my ($self)=@_;
  1022.   my ($dbh);
  1023.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  1024.             $main::opt_password,{ PrintError => 0}) ||
  1025.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  1026.   return $dbh;
  1027. }
  1028.  
  1029. sub insert_file {
  1030.   my($self,$dbname, $file) = @_;
  1031.   my($command,$sth);
  1032.   $command = "insert into $dbname from '$file'";
  1033.   print "$command\n" if ($opt_debug);
  1034.   $sth = $dbh->do($command) or die $DBI::errstr;
  1035.  
  1036.   return $sth;
  1037. }
  1038.  
  1039. #
  1040. # Returns a list of statements to create a table
  1041. # The field types are in ANSI SQL format.
  1042. #
  1043.  
  1044. sub create
  1045. {
  1046.   my($self,$table_name,$fields,$index) = @_;
  1047.   my($query,@queries,$nr);
  1048.  
  1049.   $query="create table $table_name (";
  1050.   foreach $field (@$fields)
  1051.   {
  1052.     $field =~ s/mediumint/int/i;
  1053.     $field =~ s/tinyint/int/i;
  1054.     $field =~ s/smallint/int/i;
  1055.     $field =~ s/longint/int/i;
  1056.     $field =~ s/integer/int/i;
  1057.     $field =~ s/ double/ longfloat/i;
  1058.     # Solid doesn't have blob, it has long varchar
  1059. #    $field =~ s/ blob/ text(65535,65535,65535,65535)/;
  1060.     $field =~ s/ blob/ text/;
  1061.     $field =~ s/ varchar\((\d+)\)/ char($1,3)/;
  1062.     $field =~ s/ char\((\d+)\)/ char($1,3)/;
  1063.     $field =~ s/ decimal/ float/i;
  1064.     $field =~ s/ big_decimal/ longfloat/i;
  1065.     $field =~ s/ date/ int/i;
  1066.     $field =~ s/ float(.*)/ float/i;
  1067.     if ($field =~ / int\((\d+)\)/) {
  1068.       if ($1 > 4) {
  1069.         $field =~ s/ int\(\d+\)/ longinteger/i;
  1070.       } else {
  1071.         $field =~ s/ int\(\d+\)/ longinteger/i;
  1072.       }
  1073.     } else {
  1074.       $field =~ s/ int/ longinteger/i;
  1075.     }
  1076.     $query.= $field . ',';
  1077.   }
  1078.   substr($query,-1)=")";        # Remove last ',';
  1079.   push(@queries,$query);
  1080.   $nr=1;
  1081.   foreach $index (@$index)
  1082.   {
  1083.     # Primary key is unique index in Empress
  1084.     $index =~ s/primary key/unique index/i;
  1085.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  1086.     {
  1087.       $nr++;
  1088.       push(@queries,"create unique index ${table_name}_$nr on $table_name ($1)");
  1089.     }
  1090.     else
  1091.     {
  1092.       if (!($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i))
  1093.       {
  1094.     die "Can't parse index information in '$index'\n";
  1095.       }
  1096.       push(@queries,"create $1 ${table_name}_$2 on $table_name $3");
  1097.     }
  1098.   }
  1099.   return @queries;
  1100. }
  1101.  
  1102. # empress can't handle an alias and but can handle the number of the
  1103. # columname - so
  1104. # select test as foo from tmp order by foo
  1105. # becomes
  1106. # select test from tmp order by 1
  1107. #
  1108. sub query {
  1109.   my($self,$sql) = @_;
  1110.   my(@select,$i,$tmp,$newselect,$neworder,@order,$key,%change);
  1111.   my($tmp1,$otmp,$tmp2);
  1112.  
  1113.   if ($sql =~ /\s+as\s+/i)
  1114.   {
  1115.     if ($sql =~ /select\s+(.*)\s+from/i) {
  1116.       $newselect = $1;
  1117.       (@select) = split(/,\s*/, $1);
  1118.       $i = 1;
  1119.       foreach $tmp (@select) {
  1120.     if ($tmp =~ /\s+as\s+(\w+)/) {
  1121.       $change{$1} = $i;
  1122.     }
  1123.     $i++;
  1124.       }
  1125.     }
  1126.     $newselect =~ s/\s+as\s+(\w+)//gi;
  1127.     $tmp2 = 0;
  1128.     if ($sql =~ /order\s+by\s+(.*)$/i) {
  1129.       (@order) = split(/,\s*/, $1);
  1130.       foreach $otmp (@order) {
  1131.     foreach $key (sort {$a cmp $b} keys %change) {
  1132.       if ($otmp eq $key) {
  1133.         $neworder .= "$tmp1"."$change{$key}";
  1134.         $tmp1 = ", ";
  1135.         $tmp2 = 1;
  1136.       } elsif ($otmp =~ /(\w+)\s+(.+)$/) {
  1137.         if ($key eq $1) {
  1138.           $neworder .= "$tmp1"."$change{$key} $2";
  1139.           $tmp2 = 1;
  1140.         }
  1141.       }
  1142.     }
  1143.     if ($tmp2 == 0) {
  1144.       $neworder .= "$tmp1"."$otmp";
  1145.     }
  1146.     $tmp2 = 0;
  1147.     $tmp1 = ", ";
  1148.       }
  1149.     }
  1150.     $sql =~ s/(select)\s+(.*)\s+(from)/$1 $newselect $3/i;
  1151.     $sql =~ s/(order\s+by)\s+(.*)$/$1 $neworder/i;
  1152.   }
  1153.   return $sql;
  1154. }
  1155.  
  1156. sub drop_index
  1157. {
  1158.   my ($self,$table,$index) = @_;
  1159.   return "DROP INDEX $index";
  1160. }
  1161.  
  1162. # This is a because of the 200 statement problem with DBI-Empress
  1163.  
  1164. sub abort_if_fatal_error
  1165. {
  1166.   if ($DBI::errstr =~ /Overflow of table of prepared statements/i)
  1167.   {
  1168.     print "Overflow of prepared statements ... killing the process\n";
  1169.     exit 1;
  1170.   }
  1171.   return 0;
  1172. }
  1173.  
  1174.  
  1175. #############################################################################
  1176. #                     Definitions for Oracle
  1177. #############################################################################
  1178.  
  1179. package db_Oracle;
  1180.  
  1181. sub new
  1182. {
  1183.   my ($type,$host,$database)= @_;
  1184.   my $self= {};
  1185.   my %limits;
  1186.   bless $self;
  1187.  
  1188.   $self->{'cmp_name'}        = "Oracle";
  1189.   $self->{'data_source'}    = "DBI:Oracle:$database";
  1190.   $self->{'limits'}        = \%limits;
  1191.   $self->{'smds'}        = \%smds;
  1192.   $self->{'blob'}        = "long";
  1193.   $self->{'text'}        = "long";
  1194.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  1195.  
  1196.   $limits{'max_conditions'}    = 9999; # (Actually not a limit)
  1197.   $limits{'max_columns'}    = 254;    # Max number of columns in table
  1198.   $limits{'max_text_size'}    = 2000; # Limit for blob test-connect
  1199.   $limits{'query_size'}        = 65525; # Max size with default buffers.
  1200.   $limits{'max_index'}        = 16; # Max number of keys
  1201.   $limits{'max_index_parts'}    = 16; # Max segments/key
  1202.   $limits{'max_column_name'} = 32; # max table and column name
  1203.  
  1204.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  1205.   $limits{'load_data_infile'}    = 0; # Has load data infile
  1206.   $limits{'lock_tables'}    = 0; # Has lock tables
  1207.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  1208.   $limits{'group_functions'}    = 1; # Have group functions
  1209.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  1210.   $limits{'select_without_from'}= 0;
  1211.   $limits{'multi_drop'}        = 0;
  1212.   $limits{'subqueries'}        = 1;
  1213.   $limits{'left_outer_join'}    = 0; # This may be fixed in the query module
  1214.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  1215.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  1216.   $limits{'having_with_group'}    = 1; # Can't use group functions in HAVING
  1217.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  1218.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  1219.   $limits{'group_by_position'}  = 0;
  1220.   $limits{'alter_table'}    = 1;
  1221.   $limits{'alter_add_multi_col'}= 0;
  1222.   $limits{'alter_table_dropcol'}= 0;
  1223.  
  1224.   $limits{'group_func_extra_std'}    = 0; # Have group function std().
  1225.  
  1226.   $limits{'func_odbc_mod'}    = 0; # Oracle has problem with mod()
  1227.   $limits{'func_extra_%'}    = 0; # Has % as alias for mod()
  1228.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  1229.   $limits{'func_extra_if'}    = 0; # Have function if.
  1230.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  1231.   $limits{'NEG'}        = 1; # Supports -id
  1232.   $limits{'func_extra_in_num'}    = 1; # Has function in
  1233.  
  1234.   $smds{'time'}            = 1;
  1235.   $smds{'q1'}     = 'b';        # with time not supp by mysql ('')
  1236.   $smds{'q2'}     = 'b';
  1237.   $smds{'q3'}     = 'b';        # with time ('')
  1238.   $smds{'q4'}     = 'c';        # with time not supp by mysql (d)
  1239.   $smds{'q5'}     = 'b';        # with time not supp by mysql ('')
  1240.   $smds{'q6'}     = 'c';        # with time not supp by mysql ('')
  1241.   $smds{'q7'}     = 'c';
  1242.   $smds{'q8'}     = 'f';
  1243.   $smds{'q9'}     = 'c';
  1244.   $smds{'q10'}     = 'b';
  1245.   $smds{'q11'}     = 'b';
  1246.   $smds{'q12'}     = 'd';
  1247.   $smds{'q13'}     = 'c';
  1248.   $smds{'q14'}     = 'd';
  1249.   $smds{'q15'}     = 'd';
  1250.   $smds{'q16'}     = 'a';
  1251.   $smds{'q17'}     = 'c';
  1252.  
  1253.   return $self;
  1254. }
  1255.  
  1256. #
  1257. # Get the version number of the database
  1258. #
  1259.  
  1260. sub version
  1261. {
  1262.   my ($self)=@_;
  1263.   my ($dbh,$sth,$version,@row);
  1264.  
  1265.   $dbh=$self->connect();
  1266.   $sth = $dbh->prepare("select VERSION from product_component_version WHERE PRODUCT like 'Oracle%'") or die $DBI::errstr;
  1267.   $version="Oracle 7.x";
  1268.   if ($sth->execute && (@row = $sth->fetchrow_array))
  1269.   {
  1270.     $version="Oracle $row[0]";
  1271.   }
  1272.   $sth->finish;
  1273.   $dbh->disconnect;
  1274.   return $version;
  1275. }
  1276.  
  1277. sub connect
  1278. {
  1279.   my ($self)=@_;
  1280.   my ($dbh);
  1281.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  1282.             $main::opt_password,{ PrintError => 0}) ||
  1283.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  1284.   return $dbh;
  1285. }
  1286.  
  1287. #
  1288. # Returns a list of statements to create a table
  1289. # The field types are in ANSI SQL format.
  1290. #
  1291. # If one uses $main::opt_fast then one is allowed to use
  1292. # non standard types to get better speed.
  1293. #
  1294.  
  1295. sub create
  1296. {
  1297.   my($self,$table_name,$fields,$index) = @_;
  1298.   my($query,@queries,$ind,@keys);
  1299.  
  1300.   $query="create table $table_name (";
  1301.   foreach $field (@$fields)
  1302.   {
  1303.     $field =~ s/ character\((\d+)\)/ char\($1\)/i;
  1304.     $field =~ s/ character varying\((\d+)\)/ varchar\($1\)/i;
  1305.     $field =~ s/ char varying\((\d+)\)/ varchar\($1\)/i;
  1306.     $field =~ s/ integer/ number\(38\)/i;
  1307.     $field =~ s/ int/ number\(38\)/i;
  1308.     $field =~ s/ tinyint/ number\(38\)/i;
  1309.     $field =~ s/ smallint/ number\(38\)/i;
  1310.     $field =~ s/ mediumint/ number\(38\)/i;
  1311.     $field =~ s/ tinynumber\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1312.     $field =~ s/ smallnumber\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1313.     $field =~ s/ mediumnumber\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1314.     $field =~ s/ number\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1315.     $field =~ s/ numeric\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1316.     $field =~ s/ decimal\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1317.     $field =~ s/ dec\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1318.     $field =~ s/ float/ number/;
  1319.     $field =~ s/ real/ number/;
  1320.     $field =~ s/ double precision/ number/;
  1321.     $field =~ s/ double/ number/;
  1322.     $field =~ s/ blob/ long/;
  1323.     $query.= $field . ',';
  1324.   }
  1325.  
  1326.   foreach $ind (@$index)
  1327.   {
  1328.     my @index;
  1329.     if ( $ind =~ /\bKEY\b/i ){
  1330.       push(@keys,"ALTER TABLE $table_name ADD $ind");
  1331.     }else{
  1332.       my @fields = split(' ',$index);
  1333.       my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
  1334.       push(@index,$query);
  1335.     }
  1336.   }
  1337.   substr($query,-1)=")";        # Remove last ',';
  1338.   push(@queries,$query,@keys,@index);
  1339. #print "query:$query\n";
  1340.  
  1341.   return @queries;
  1342. }
  1343.  
  1344. sub insert_file {
  1345.   my($self,$dbname, $file) = @_;
  1346.   print "insert an ascii file isn't supported by Oracle (?)\n";
  1347.   return 0;
  1348. }
  1349.  
  1350. #
  1351. # Do any conversions to the ANSI SQL query so that the database can handle it
  1352. #
  1353.  
  1354. sub query {
  1355.   my($self,$sql) = @_;
  1356.   return $sql;
  1357. }
  1358.  
  1359. sub drop_index
  1360. {
  1361.   my ($self,$table,$index) = @_;
  1362.   return "DROP INDEX $index";
  1363. }
  1364.  
  1365. #
  1366. # Abort if the server has crashed
  1367. # return: 0 if ok
  1368. #      1 question should be retried
  1369. #
  1370.  
  1371. sub abort_if_fatal_error
  1372. {
  1373.   return 0;
  1374. }
  1375.  
  1376. #
  1377. # optimize the tables ....
  1378. #
  1379. sub vacuum
  1380. {
  1381.   my ($self,$dbh)=@_;
  1382.   my ($loop_time,$end_time);
  1383.   $loop_time=new Benchmark;
  1384.   $dbh->do("analyze table ?? compute statistics") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
  1385.   $end_time=new Benchmark;
  1386.   print "Time for book-keeping (1): " .
  1387.   Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"noc") . "\n\n";
  1388. }
  1389.  
  1390.  
  1391. #############################################################################
  1392. #                     Definitions for Informix
  1393. #############################################################################
  1394.  
  1395. package db_Informix;
  1396.  
  1397. sub new
  1398. {
  1399.   my ($type,$host,$database)= @_;
  1400.   my $self= {};
  1401.   my %limits;
  1402.   bless $self;
  1403.  
  1404.   $self->{'cmp_name'}        = "Informix";
  1405.   $self->{'data_source'}    = "DBI:Informix:$database";
  1406.   $self->{'limits'}        = \%limits;
  1407.   $self->{'smds'}        = \%smds;
  1408.   $self->{'blob'}        = "byte in table";
  1409.   $self->{'text'}        = "byte in table";
  1410.   $self->{'double_quotes'}    = 0; # Can handle:  'Walker''s'
  1411.   $self->{'host'}        = $main::opt_host;
  1412.  
  1413.   $limits{'NEG'}        = 1; # Supports -id
  1414.   $limits{'alter_table'}    = 1;
  1415.   $limits{'alter_add_multi_col'}= 0;
  1416.   $limits{'alter_table_dropcol'}= 1;
  1417.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  1418.   $limits{'func_extra_%'}    = 0; # Has % as alias for mod()
  1419.   $limits{'func_extra_if'}    = 0; # Have function if.
  1420.   $limits{'func_extra_in_num'}= 0; # Has function in
  1421.   $limits{'func_odbc_floor'}    = 0; # Has func_odbc_floor function
  1422.   $limits{'func_odbc_mod'}    = 1; # Have function mod.
  1423.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  1424.   $limits{'group_by_position'}  = 1; # Can use 'GROUP BY 1'
  1425.   $limits{'group_by_alias'}  = 0; # Can use 'select a as ab from x GROUP BY ab'
  1426.   $limits{'group_func_extra_std'} = 0; # Have group function std().
  1427.   $limits{'group_functions'}    = 1; # Have group functions
  1428.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  1429.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  1430.   $limits{'having_with_group'}= 1; # Can't use group functions in HAVING
  1431.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables (always 1 only for msql)
  1432.   $limits{'left_outer_join'}    = 0; # Supports left outer joins (ANSI)
  1433.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  1434.   $limits{'load_data_infile'}    = 0; # Has load data infile
  1435.   $limits{'lock_tables'}    = 1; # Has lock tables
  1436.   $limits{'max_conditions'}    = 1214; # (Actually not a limit)
  1437.   $limits{'max_column_name'}    = 18; # max table and column name
  1438.   $limits{'max_columns'}    = 994;    # Max number of columns in table
  1439.   $limits{'max_index'}        = 64; # Max number of keys
  1440.   $limits{'max_index_parts'}    = 15; # Max segments/key
  1441.   $limits{'max_text_size'}    = 65535;  # Max size with default buffers. ??
  1442.   $limits{'multi_drop'}        = 0; # Drop table can take many tables
  1443.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  1444.   $limits{'query_size'}        = 32766; # Max size with default buffers.
  1445.   $limits{'select_without_from'}= 0; # Can do 'select 1';
  1446.   $limits{'subqueries'}        = 1; # Doesn't support sub-queries.
  1447.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  1448.  
  1449.  
  1450.   return $self;
  1451. }
  1452.  
  1453. #
  1454. # Get the version number of the database
  1455. #
  1456.  
  1457. sub version
  1458. {
  1459.   my ($self)=@_;
  1460.   my ($dbh,$sth,$version,@row);
  1461.  
  1462.   $ENV{'INFORMIXSERVER'} = $self->{'host'};
  1463.   $dbh=$self->connect();
  1464.   $sth = $dbh->prepare("SELECT owner FROM systables WHERE tabname = ' VERSION'")
  1465.                               or die $DBI::errstr;
  1466.   $version='Informix unknown';
  1467.   if ($sth->execute && (@row = $sth->fetchrow_array))
  1468.   {
  1469.     $version="Informix $row[0]";
  1470.   }
  1471.   $sth->finish;
  1472.   $dbh->disconnect;
  1473.   return $version;
  1474. }
  1475.  
  1476. sub connect
  1477. {
  1478.   my ($self)=@_;
  1479.   my ($dbh);
  1480.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  1481.             $main::opt_password,{ PrintError => 0}) ||
  1482.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  1483.   return $dbh;
  1484. }
  1485.  
  1486.  
  1487. #
  1488. # Create table
  1489. #
  1490.  
  1491. sub create
  1492. {
  1493.   my($self,$table_name,$fields,$index) = @_;
  1494.   my($query,@queries,$name,$nr);
  1495.  
  1496.   $query="create table $table_name (";
  1497.   foreach $field (@$fields)
  1498.   {
  1499. #    $field =~ s/\btransport_description\b/transport_desc/;
  1500.                 # to overcome limit 18 chars
  1501.     $field =~ s/tinyint/smallint/i;
  1502.     $field =~ s/tinyint\(\d+\)/smallint/i;
  1503.     $field =~ s/mediumint/integer/i;
  1504.     $field =~ s/mediumint\(\d+\)/integer/i;
  1505.     $field =~ s/smallint\(\d+\)/smallint/i;
  1506.     $field =~ s/integer\(\d+\)/integer/i;
  1507.     $field =~ s/int\(\d+\)/integer/i;
  1508. #    $field =~ s/\b(?:small)?int(?:eger)?\((\d+)\)/decimal($1)/i;
  1509. #    $field =~ s/float(\(\d*,\d*\)){0,1}/real/i;
  1510.     $field =~ s/(float|double)(\(.*?\))?/float/i;
  1511.  
  1512.     if ($field =~ / blob/i)
  1513.     {
  1514.       $name=$self->{'blob'};
  1515.       $field =~ s/ blob/ $name/;
  1516.     }
  1517.     $query.= $field . ',';
  1518.   }
  1519.   substr($query,-1)=")";        # Remove last ',';
  1520.   push(@queries,$query);
  1521.   $nr=0;
  1522.  
  1523.   foreach $index (@$index)
  1524.   {
  1525.     # Primary key is unique index in Informix
  1526.     $index =~ s/primary key/unique index primary/i;
  1527.     if ($index =~ /^unique\s*\(([^\(]*)\)$/i)
  1528.     {
  1529.       $nr++;
  1530.       push(@queries,"create unique index ${table_name}_$nr on $table_name ($1)");
  1531.     }
  1532.     else
  1533.     {
  1534.       if (!($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i))
  1535.       {
  1536.     die "Can't parse index information in '$index'\n";
  1537.       }
  1538.       ### push(@queries,"create $1 ${table_name}_$2 on $table_name $3");
  1539.       $nr++;
  1540.       push(@queries,"create $1 ${table_name}_$nr on $table_name $3");
  1541.     }
  1542.   }
  1543.   return @queries;
  1544. }
  1545. #
  1546. # Some test needed this
  1547. #
  1548.  
  1549. sub query {
  1550.   my($self,$sql) = @_;
  1551.   return $sql;
  1552. }
  1553.  
  1554. sub drop_index
  1555. {
  1556.   my ($self,$table,$index) = @_;
  1557.   return "DROP INDEX $index";
  1558. }
  1559.  
  1560. #
  1561. # Abort if the server has crashed
  1562. # return: 0 if ok
  1563. #      1 question should be retried
  1564. #
  1565.  
  1566. sub abort_if_fatal_error
  1567. {
  1568.   return 0;
  1569. }
  1570.  
  1571. #############################################################################
  1572. #         Configuration for Access
  1573. #############################################################################
  1574.  
  1575. package db_access;
  1576.  
  1577. sub new
  1578. {
  1579.   my ($type,$host,$database)= @_;
  1580.   my $self= {};
  1581.   my %limits;
  1582.   bless $self;
  1583.  
  1584.   $self->{'cmp_name'}        = "access";
  1585.   $self->{'data_source'}    = "DBI:ODBC:$database";
  1586.   if (defined($opt_host) && $opt_host ne "")
  1587.   {
  1588.     $self->{'data_source'}    .= ":$host";
  1589.   }
  1590.   $self->{'limits'}        = \%limits;
  1591.   $self->{'smds'}        = \%smds;
  1592.   $self->{'blob'}        = "blob";
  1593.   $self->{'text'}        = "blob"; # text ? 
  1594.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  1595.  
  1596.   $limits{'max_conditions'}    = 86; # We get 'Query is too complex'
  1597.   $limits{'max_columns'}    = 255;    # Max number of columns in table
  1598.   $limits{'max_text_size'}    = 255;  # Max size with default buffers.
  1599.   $limits{'query_size'}        = 16402; # Max size with default buffers.
  1600.   $limits{'max_index'}        = 32; # Max number of keys
  1601.   $limits{'max_index_parts'}    = 10; # Max segments/key
  1602.   $limits{'max_column_name'}    = 64; # max table and column name
  1603.  
  1604.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  1605.   $limits{'load_data_infile'}    = 0; # Has load data infile
  1606.   $limits{'lock_tables'}    = 0; # Has lock tables
  1607.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  1608.   $limits{'group_functions'}    = 1; # Have group functions
  1609.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  1610.   $limits{'select_without_from'}= 0; # Can do 'select 1';
  1611.   $limits{'multi_drop'}        = 0; # Drop table can take many tables
  1612.   $limits{'subqueries'}        = 1; # Supports sub-queries.
  1613.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  1614.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  1615.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  1616.   $limits{'having_with_group'}    = 0; # Can't use group functions in HAVING
  1617.   $limits{'like_with_column'}    = 0; # Can use column1 LIKE column2
  1618.   $limits{'order_by_position'}  = 0; # Can use 'ORDER BY 1'
  1619.   $limits{'group_by_position'}  = 0; # Can use 'GROUP BY 1'
  1620.   $limits{'alter_table'}    = 1;
  1621.   $limits{'alter_add_multi_col'}= 0;
  1622.   $limits{'alter_table_dropcol'}= 0;
  1623.  
  1624.   $limits{'group_func_extra_std'} = 0; # Have group function std().
  1625.  
  1626.   $limits{'func_odbc_mod'}    = 0; # Have function mod.
  1627.   $limits{'func_extra_%'}    = 0; # Has % as alias for mod()
  1628.   $limits{'func_odbc_floor'}    = 0; # Has func_odbc_floor function
  1629.   $limits{'func_extra_if'}    = 0; # Have function if.
  1630.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  1631.   $limits{'NEG'}        = 1; # Supports -id
  1632.   $limits{'func_extra_in_num'}    = 1; # Has function in
  1633.   return $self;
  1634. }
  1635.  
  1636. #
  1637. # Get the version number of the database
  1638. #
  1639.  
  1640. sub version
  1641. {
  1642.   my ($self)=@_;
  1643.   return "Access 97";        #DBI/ODBC can't return the server version
  1644. }
  1645.  
  1646. sub connect
  1647. {
  1648.   my ($self)=@_;
  1649.   my ($dbh);
  1650.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  1651.             $main::opt_password,{ PrintError => 0}) ||
  1652.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  1653.   return $dbh;
  1654. }
  1655.  
  1656. #
  1657. # Returns a list of statements to create a table
  1658. # The field types are in ANSI SQL format.
  1659. #
  1660.  
  1661. sub create
  1662. {
  1663.   my($self,$table_name,$fields,$index) = @_;
  1664.   my($query,@queries,$nr);
  1665.  
  1666.   $query="create table $table_name (";
  1667.   foreach $field (@$fields)
  1668.   {
  1669.     $field =~ s/mediumint/integer/i;
  1670.     $field =~ s/tinyint/smallint/i;
  1671.     $field =~ s/float\(\d+,\d+\)/float/i;
  1672.     $field =~ s/integer\(\d+\)/integer/i;
  1673.     $field =~ s/smallint\(\d+\)/smallint/i;
  1674.     $field =~ s/int\(\d+\)/integer/i;
  1675.     $field =~ s/blob/text/i;
  1676.     $query.= $field . ',';
  1677.   }
  1678.   substr($query,-1)=")";        # Remove last ',';
  1679.   push(@queries,$query);
  1680.   $nr=0;
  1681.   foreach $index (@$index)
  1682.   {
  1683.     $ext="WITH DISALLOW NULL";
  1684.     if (($index =~ s/primary key/unique index primary_key/i))
  1685.     {
  1686.       $ext="WITH PRIMARY;"
  1687.     }
  1688.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  1689.     {
  1690.       $nr++;
  1691.       $index="unique index ${table_name}_$nr ($1)";
  1692.     }
  1693.     $index =~ /^(.*)\s+(\(.*\))$/;
  1694.     push(@queries,"create ${1} on $table_name $2");
  1695.   }
  1696.   return @queries;
  1697. }
  1698.  
  1699. #
  1700. # Do any conversions to the ANSI SQL query so that the database can handle it
  1701. #
  1702.  
  1703. sub query {
  1704.   my($self,$sql) = @_;
  1705.   return $sql;
  1706. }
  1707.  
  1708. sub drop_index
  1709. {
  1710.   my ($self,$table,$index) = @_;
  1711.   return "DROP INDEX $index ON $table";
  1712. }
  1713.  
  1714. #
  1715. # Abort if the server has crashed
  1716. # return: 0 if ok
  1717. #      1 question should be retried
  1718. #
  1719.  
  1720. sub abort_if_fatal_error
  1721. {
  1722.   return 1 if (($DBI::errstr =~ /The database engine couldn\'t lock table/i) ||
  1723.                ($DBI::errstr =~ /niet vergrendelen. De tabel is momenteel in gebruik /i));
  1724.   return 0;
  1725. }
  1726.  
  1727. #############################################################################
  1728. #         Configuration for Microsoft SQL server
  1729. #############################################################################
  1730.  
  1731. package db_ms_sql;
  1732.  
  1733. sub new
  1734. {
  1735.   my ($type,$host,$database)= @_;
  1736.   my $self= {};
  1737.   my %limits;
  1738.   bless $self;
  1739.  
  1740.   $self->{'cmp_name'}        = "ms-sql";
  1741.   $self->{'data_source'}    = "DBI:ODBC:$database";
  1742.   if (defined($opt_host) && $opt_host ne "")
  1743.   {
  1744.     $self->{'data_source'}    .= ":$host";
  1745.   }
  1746.   $self->{'limits'}        = \%limits;
  1747.   $self->{'smds'}        = \%smds;
  1748.   $self->{'blob'}        = "text";
  1749.   $self->{'text'}        = "text";
  1750.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  1751.  
  1752.   $limits{'max_conditions'}    = 1030; # We get 'Query is too complex'
  1753.   $limits{'max_columns'}    = 250;    # Max number of columns in table
  1754.   $limits{'max_text_size'}    = 9830;  # Max size with default buffers.
  1755.   $limits{'query_size'}        = 9830; # Max size with default buffers.
  1756.   $limits{'max_index'}        = 64; # Max number of keys
  1757.   $limits{'max_index_parts'}    = 15; # Max segments/key
  1758.   $limits{'max_column_name'}    = 30; # max table and column name
  1759.  
  1760.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  1761.   $limits{'load_data_infile'}    = 0; # Has load data infile
  1762.   $limits{'lock_tables'}    = 0; # Has lock tables
  1763.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  1764.   $limits{'group_functions'}    = 1; # Have group functions
  1765.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  1766.   $limits{'select_without_from'}= 1; # Can do 'select 1';
  1767.   $limits{'multi_drop'}        = 1; # Drop table can take many tables
  1768.   $limits{'subqueries'}        = 1; # Supports sub-queries.
  1769.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  1770.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  1771.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  1772.   $limits{'having_with_group'}    = 1; # Can't use group functions in HAVING
  1773.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  1774.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  1775.   $limits{'group_by_position'}  = 0; # Can use 'GROUP BY 1'
  1776.   $limits{'alter_table'}    = 1;
  1777.   $limits{'alter_add_multi_col'}= 0;
  1778.   $limits{'alter_table_dropcol'}= 0;
  1779.  
  1780.   $limits{'group_func_extra_std'} = 0; # Have group function std().
  1781.  
  1782.   $limits{'func_odbc_mod'}    = 0; # Have function mod.
  1783.   $limits{'func_extra_%'}    = 1; # Has % as alias for mod()
  1784.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  1785.   $limits{'func_extra_if'}    = 0; # Have function if.
  1786.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  1787.   $limits{'NEG'}        = 1; # Supports -id
  1788.   $limits{'func_extra_in_num'}    = 0; # Has function in
  1789.   return $self;
  1790. }
  1791.  
  1792. #
  1793. # Get the version number of the database
  1794. #
  1795.  
  1796. sub version
  1797. {
  1798.   my ($self)=@_;
  1799.   my($sth,@row);
  1800.   $dbh=$self->connect();
  1801.   $sth = $dbh->prepare("SELECT \@\@VERSION") or die $DBI::errstr;
  1802.   $sth->execute or die $DBI::errstr;
  1803.   @row = $sth->fetchrow_array;
  1804.   if ($row[0]) {
  1805.      @server = split(/\n/,$row[0]);
  1806.      chomp(@server);
  1807.      return "$server[0]";
  1808.   } else {
  1809.     return "Microsoft SQL server ?";
  1810.   }
  1811. }
  1812.  
  1813. sub connect
  1814. {
  1815.   my ($self)=@_;
  1816.   my ($dbh);
  1817.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  1818.             $main::opt_password,{ PrintError => 0}) ||
  1819.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  1820.   return $dbh;
  1821. }
  1822.  
  1823. #
  1824. # Returns a list of statements to create a table
  1825. # The field types are in ANSI SQL format.
  1826. #
  1827.  
  1828. sub create
  1829. {
  1830.   my($self,$table_name,$fields,$index) = @_;
  1831.   my($query,@queries,$nr);
  1832.  
  1833.   $query="create table $table_name (";
  1834.   foreach $field (@$fields)
  1835.   {
  1836.     $field =~ s/mediumint/integer/i;
  1837.     $field =~ s/float\(\d+,\d+\)/float/i;
  1838.     $field =~ s/double\(\d+,\d+\)/float/i;
  1839.     $field =~ s/double/float/i;
  1840.     $field =~ s/integer\(\d+\)/integer/i;
  1841.     $field =~ s/int\(\d+\)/integer/i;
  1842.     $field =~ s/smallint\(\d+\)/smallint/i;
  1843.     $field =~ s/smallinteger/smallint/i;
  1844.     $field =~ s/tinyint\(\d+\)/tinyint/i;
  1845.     $field =~ s/tinyinteger/tinyint/i;
  1846.     $field =~ s/blob/text/i;
  1847.     $query.= $field . ',';
  1848.   }
  1849.   substr($query,-1)=")";        # Remove last ',';
  1850.   push(@queries,$query);
  1851.   $nr=0;
  1852.   foreach $index (@$index)
  1853.   {
  1854.     $ext="WITH DISALLOW NULL";
  1855.     if (($index =~ s/primary key/unique index primary_key/i))
  1856.     {
  1857.       $ext="WITH PRIMARY;"
  1858.     }
  1859.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  1860.     {
  1861.       $nr++;
  1862.       $index="unique index ${table_name}_$nr ($1)";
  1863.     }
  1864.     $index =~ /^(.*)\s+(\(.*\))$/;
  1865.     push(@queries,"create ${1} on $table_name $2");
  1866.   }
  1867.   return @queries;
  1868. }
  1869.  
  1870. #
  1871. # Do any conversions to the ANSI SQL query so that the database can handle it
  1872. #
  1873.  
  1874. sub query {
  1875.   my($self,$sql) = @_;
  1876.   return $sql;
  1877. }
  1878.  
  1879. sub drop_index
  1880. {
  1881.   my ($self,$table,$index) = @_;
  1882.   return "DROP INDEX $table.$index";
  1883. }
  1884.  
  1885. #
  1886. # Abort if the server has crashed
  1887. # return: 0 if ok
  1888. #      1 question should be retried
  1889. #
  1890.  
  1891. sub abort_if_fatal_error
  1892. {
  1893.   return 0;
  1894. }
  1895. #############################################################################
  1896. #         Configuration for Sybase
  1897. #############################################################################
  1898.  
  1899. package db_sybase;
  1900.  
  1901. sub new
  1902. {
  1903.   my ($type,$host,$database)= @_;
  1904.   my $self= {};
  1905.   my %limits;
  1906.   bless $self;
  1907.  
  1908.   $self->{'cmp_name'}        = "sybase";
  1909.   $self->{'data_source'}    = "DBI:ODBC:$database";
  1910.   if (defined($opt_host) && $opt_host ne "")
  1911.   {
  1912.     $self->{'data_source'}    .= ":$host";
  1913.   }
  1914.   $self->{'limits'}        = \%limits;
  1915.   $self->{'smds'}        = \%smds;
  1916.   $self->{'blob'}        = "text";
  1917.   $self->{'text'}        = "text";
  1918.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  1919.  
  1920.   $limits{'max_conditions'}    = 1030; # We get 'Query is too complex'
  1921.   $limits{'max_columns'}    = 250;    # Max number of columns in table
  1922.   $limits{'max_text_size'}    = 9830;  # Max size with default buffers.
  1923.   $limits{'query_size'}        = 9830; # Max size with default buffers.
  1924.   $limits{'max_index'}        = 64; # Max number of keys
  1925.   $limits{'max_index_parts'}    = 15; # Max segments/key
  1926.   $limits{'max_column_name'}    = 30; # max table and column name
  1927.  
  1928.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  1929.   $limits{'load_data_infile'}    = 0; # Has load data infile
  1930.   $limits{'lock_tables'}    = 0; # Has lock tables
  1931.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  1932.   $limits{'group_functions'}    = 1; # Have group functions
  1933.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  1934.   $limits{'select_without_from'}= 1; # Can do 'select 1';
  1935.   $limits{'multi_drop'}        = 1; # Drop table can take many tables
  1936.   $limits{'subqueries'}        = 1; # Supports sub-queries.
  1937.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  1938.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  1939.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  1940.   $limits{'having_with_group'}    = 1; # Can't use group functions in HAVING
  1941.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  1942.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  1943.   $limits{'group_by_position'}  = 0; # Can use 'GROUP BY 1'
  1944.   $limits{'alter_table'}    = 1;
  1945.   $limits{'alter_add_multi_col'}= 0;
  1946.   $limits{'alter_table_dropcol'}= 0;
  1947.  
  1948.   $limits{'group_func_extra_std'} = 0; # Have group function std().
  1949.  
  1950.   $limits{'func_odbc_mod'}    = 0; # Have function mod.
  1951.   $limits{'func_extra_%'}    = 1; # Has % as alias for mod()
  1952.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  1953.   $limits{'func_extra_if'}    = 0; # Have function if.
  1954.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  1955.   $limits{'NEG'}        = 1; # Supports -id
  1956.   $limits{'func_extra_in_num'}    = 0; # Has function in
  1957.   return $self;
  1958. }
  1959.  
  1960. #
  1961. # Get the version number of the database
  1962. #
  1963.  
  1964. sub version
  1965. {
  1966.   my ($self)=@_;
  1967.   return "Sybase enterprise 11.5 NT";        #DBI/ODBC can't return the server version
  1968. }
  1969.  
  1970. sub connect
  1971. {
  1972.   my ($self)=@_;
  1973.   my ($dbh);
  1974.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  1975.             $main::opt_password,{ PrintError => 0}) ||
  1976.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  1977.   return $dbh;
  1978. }
  1979.  
  1980. #
  1981. # Returns a list of statements to create a table
  1982. # The field types are in ANSI SQL format.
  1983. #
  1984.  
  1985. sub create
  1986. {
  1987.   my($self,$table_name,$fields,$index) = @_;
  1988.   my($query,@queries,$nr);
  1989.  
  1990.   $query="create table $table_name (";
  1991.   foreach $field (@$fields)
  1992.   {
  1993.     $field =~ s/mediumint/integer/i;
  1994.     $field =~ s/float\(\d+,\d+\)/float/i;
  1995.     $field =~ s/int\(\d+\)/int/i;
  1996.     $field =~ s/double/float/i;
  1997.     $field =~ s/integer\(\d+\)/integer/i;
  1998.     $field =~ s/smallint\(\d+\)/smallint/i;
  1999.     $field =~ s/tinyint\(\d+\)/tinyint/i;
  2000.     $field =~ s/blob/text/i;
  2001.     $query.= $field . ',';
  2002.   }
  2003.   substr($query,-1)=")";        # Remove last ',';
  2004.   push(@queries,$query);
  2005.   $nr=0;
  2006.   foreach $index (@$index)
  2007.   {
  2008. #    $ext="WITH DISALLOW NULL";
  2009.     if (($index =~ s/primary key/unique index primary_key/i))
  2010.     {
  2011. #      $ext="WITH PRIMARY;"
  2012.     }
  2013.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  2014.     {
  2015.       $nr++;
  2016.       $index="unique index ${table_name}_$nr ($1)";
  2017.     }
  2018.     $index =~ /^(.*)\s+(\(.*\))$/;
  2019.     push(@queries,"create ${1} on $table_name $2");
  2020.   }
  2021.   return @queries;
  2022. }
  2023.  
  2024. #
  2025. # Do any conversions to the ANSI SQL query so that the database can handle it
  2026. #
  2027.  
  2028. sub query {
  2029.   my($self,$sql) = @_;
  2030.   return $sql;
  2031. }
  2032.  
  2033. sub drop_index
  2034. {
  2035.   my ($self,$table,$index) = @_;
  2036.   return "DROP INDEX $table.$index";
  2037. }
  2038.  
  2039. #
  2040. # Abort if the server has crashed
  2041. # return: 0 if ok
  2042. #      1 question should be retried
  2043. #
  2044.  
  2045. sub abort_if_fatal_error
  2046. {
  2047.   return 0;
  2048. }
  2049. #
  2050. # optimize the tables ....
  2051. #
  2052. sub vacuum
  2053. {
  2054.   my ($self,$dbh)=@_;
  2055.   my ($loop_time,$end_time);
  2056.   $loop_time=new Benchmark;
  2057.   $dbh->do("analyze table ?? compute statistics") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
  2058.   $end_time=new Benchmark;
  2059.   print "Time for book-keeping (1): " .
  2060.   Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"noc") . "\n\n";
  2061. }
  2062.  
  2063.  
  2064. #############################################################################
  2065. #                     Definitions for Adabas
  2066. #############################################################################
  2067.  
  2068. package db_Adabas;
  2069.  
  2070. sub new
  2071. {
  2072.   my ($type,$host,$database)= @_;
  2073.   my $self= {};
  2074.   my %limits;
  2075.   bless $self;
  2076.  
  2077.   $self->{'cmp_name'}        = "Adabas";
  2078.   $self->{'data_source'}    = "DBI:Adabas:$database";
  2079.   $self->{'limits'}        = \%limits;
  2080.   $self->{'smds'}        = \%smds;
  2081.   $self->{'blob'}        = "long";
  2082.   $self->{'text'}        = "long";
  2083.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  2084.  
  2085.   $limits{'max_conditions'}    = 50; # (Actually not a limit)
  2086.   $limits{'max_columns'}    = 254;    # Max number of columns in table
  2087.   $limits{'max_text_size'}    = 2000; # Limit for blob test-connect
  2088.   $limits{'query_size'}        = 65525; # Max size with default buffers.
  2089.   $limits{'max_index'}        = 16; # Max number of keys
  2090.   $limits{'max_index_parts'}    = 16; # Max segments/key
  2091.   $limits{'max_column_name'} = 32; # max table and column name
  2092.  
  2093.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  2094.   $limits{'load_data_infile'}    = 0; # Has load data infile
  2095.   $limits{'lock_tables'}    = 0; # Has lock tables
  2096.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  2097.   $limits{'group_functions'}    = 1; # Have group functions
  2098.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  2099.   $limits{'select_without_from'}= 0;
  2100.   $limits{'multi_drop'}        = 0;
  2101.   $limits{'subqueries'}        = 1;
  2102.   $limits{'left_outer_join'}    = 0; # This may be fixed in the query module
  2103.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  2104.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  2105.   $limits{'having_with_group'}    = 1; # Can't use group functions in HAVING
  2106.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  2107.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  2108.   $limits{'group_by_position'}  = 1;
  2109.   $limits{'alter_table'}    = 1;
  2110.   $limits{'alter_add_multi_col'}= 2; #Have ALTER TABLE t add a int, b int;
  2111.   $limits{'alter_table_dropcol'}= 1;
  2112.  
  2113.   $limits{'group_func_extra_std'}    = 0; # Have group function std().
  2114.  
  2115.   $limits{'func_odbc_mod'}    = 0; # Oracle has problem with mod()
  2116.   $limits{'func_extra_%'}    = 0; # Has % as alias for mod()
  2117.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  2118.   $limits{'func_extra_if'}    = 0; # Have function if.
  2119.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  2120.   $limits{'NEG'}        = 1; # Supports -id
  2121.   $limits{'func_extra_in_num'}    = 1; # Has function in
  2122.  
  2123.   $smds{'time'}            = 1;
  2124.   $smds{'q1'}     = 'b';        # with time not supp by mysql ('')
  2125.   $smds{'q2'}     = 'b';
  2126.   $smds{'q3'}     = 'b';        # with time ('')
  2127.   $smds{'q4'}     = 'c';        # with time not supp by mysql (d)
  2128.   $smds{'q5'}     = 'b';        # with time not supp by mysql ('')
  2129.   $smds{'q6'}     = 'c';        # with time not supp by mysql ('')
  2130.   $smds{'q7'}     = 'c';
  2131.   $smds{'q8'}     = 'f';
  2132.   $smds{'q9'}     = 'c';
  2133.   $smds{'q10'}     = 'b';
  2134.   $smds{'q11'}     = 'b';
  2135.   $smds{'q12'}     = 'd';
  2136.   $smds{'q13'}     = 'c';
  2137.   $smds{'q14'}     = 'd';
  2138.   $smds{'q15'}     = 'd';
  2139.   $smds{'q16'}     = 'a';
  2140.   $smds{'q17'}     = 'c';
  2141.  
  2142.   return $self;
  2143. }
  2144.  
  2145. #
  2146. # Get the version number of the database
  2147. #
  2148.  
  2149. sub version
  2150. {
  2151.   my ($self)=@_;
  2152.   my ($dbh,$sth,$version,@row);
  2153.  
  2154.   $dbh=$self->connect();
  2155.   $sth = $dbh->prepare("SELECT KERNEL FROM VERSIONS") or die $DBI::errstr;
  2156.   $version="Adabas (unknown)";
  2157.   if ($sth->execute && (@row = $sth->fetchrow_array)
  2158.       && $row[0] =~ /([\d\.]+)/)
  2159.   {
  2160.     $version="Adabas $1";
  2161.   }
  2162.   $sth->finish;
  2163.   $dbh->disconnect;
  2164.   return $version;
  2165. }
  2166.  
  2167. sub connect
  2168. {
  2169.   my ($self)=@_;
  2170.   my ($dbh);
  2171.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  2172.             $main::opt_password,{ PrintError => 0}) ||
  2173.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  2174.   return $dbh;
  2175. }
  2176.  
  2177. #
  2178. # Returns a list of statements to create a table
  2179. # The field types are in ANSI SQL format.
  2180. #
  2181. # If one uses $main::opt_fast then one is allowed to use
  2182. # non standard types to get better speed.
  2183. #
  2184.  
  2185. sub create
  2186. {
  2187.   my($self,$table_name,$fields,$index) = @_;
  2188.   my($query,@queries,$ind,@keys);
  2189.  
  2190.   $query="create table $table_name (";
  2191.   foreach $field (@$fields)
  2192.   {
  2193.     $field =~ s/CHARACTER\s+VARYING/VARCHAR/i;
  2194.     $field =~ s/TINYINT/SMALLINT/i;
  2195.     $field =~ s/MEDIUMINT/INT/i;
  2196.     $field =~ s/SMALLINT\s*\(\d+\)/SMALLINT/i;
  2197.     $field =~ s/INT\s*\(\d+\)/INT/i;
  2198.     $field =~ s/BLOB/LONG/i;
  2199.     $field =~ s/INTEGER\s*\(\d+\)/INTEGER/i;
  2200.     $field =~ s/FLOAT\s*\((\d+),\d+\)/FLOAT\($1\)/i;
  2201.     $field =~ s/DOUBLE/FLOAT\(38\)/i;
  2202.     $field =~ s/DOUBLE\s+PRECISION/FLOAT\(38\)/i;
  2203.     $query.= $field . ',';
  2204.   }
  2205.  
  2206.   foreach $ind (@$index)
  2207.   {
  2208.     my @index;
  2209.     if ( $ind =~ /\bKEY\b/i ){
  2210.       push(@keys,"ALTER TABLE $table_name ADD $ind");
  2211.     }else{
  2212.       my @fields = split(' ',$index);
  2213.       my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
  2214.       push(@index,$query);
  2215.     }
  2216.   }
  2217.   substr($query,-1)=")";        # Remove last ',';
  2218.   push(@queries,$query,@keys,@index);
  2219. #print "query:$query\n";
  2220.  
  2221.   return @queries;
  2222. }
  2223.  
  2224. sub insert_file {
  2225.   my($self,$dbname, $file) = @_;
  2226.   print "insert an ascii file isn't supported by Oracle (?)\n";
  2227.   return 0;
  2228. }
  2229.  
  2230. #
  2231. # Do any conversions to the ANSI SQL query so that the database can handle it
  2232. #
  2233.  
  2234. sub query {
  2235.   my($self,$sql) = @_;
  2236.   return $sql;
  2237. }
  2238.  
  2239. sub drop_index
  2240. {
  2241.   my ($self,$table,$index) = @_;
  2242.   return "DROP INDEX $index";
  2243. }
  2244.  
  2245. #
  2246. # Abort if the server has crashed
  2247. # return: 0 if ok
  2248. #      1 question should be retried
  2249. #
  2250.  
  2251. sub abort_if_fatal_error
  2252. {
  2253.   return 0;
  2254. }
  2255.  
  2256. #############################################################################
  2257. #         Configuration for IBM DB2
  2258. #############################################################################
  2259.  
  2260. package db_db2;
  2261.  
  2262. sub new
  2263. {
  2264.   my ($type,$host,$database)= @_;
  2265.   my $self= {};
  2266.   my %limits;
  2267.   bless $self;
  2268.  
  2269.   $self->{'cmp_name'}        = "DB2";
  2270.   $self->{'data_source'}    = "DBI:ODBC:$database";
  2271.   if (defined($opt_host) && $opt_host ne "")
  2272.   {
  2273.     $self->{'data_source'}    .= ":$host";
  2274.   }
  2275.   $self->{'limits'}        = \%limits;
  2276.   $self->{'smds'}        = \%smds;
  2277.   $self->{'blob'}        = "varchar(255)";
  2278.   $self->{'text'}        = "varchar(255)";
  2279.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  2280.  
  2281.   $limits{'max_conditions'}    = 418; # We get 'Query is too complex'
  2282.   $limits{'max_columns'}    = 500;    # Max number of columns in table
  2283.   $limits{'max_text_size'}    = 254;  # Max size with default buffers.
  2284.   $limits{'query_size'}        = 254; # Max size with default buffers.
  2285.   $limits{'max_index'}        = 48; # Max number of keys
  2286.   $limits{'max_index_parts'}    = 15; # Max segments/key
  2287.   $limits{'max_column_name'}    = 18; # max table and column name
  2288.  
  2289.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  2290.   $limits{'load_data_infile'}    = 0; # Has load data infile
  2291.   $limits{'lock_tables'}    = 0; # Has lock tables
  2292.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  2293.   $limits{'group_functions'}    = 1; # Have group functions
  2294.   $limits{'group_func_sql_min_str'}= 1;
  2295.   $limits{'select_without_from'}= 0; # Can do 'select 1';
  2296.   $limits{'multi_drop'}        = 0; # Drop table can take many tables
  2297.   $limits{'subqueries'}        = 1; # Supports sub-queries.
  2298.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  2299.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  2300.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  2301.   $limits{'having_with_group'}    = 1; # Can't use group functions in HAVING
  2302.   $limits{'like_with_column'}    = 0; # Can use column1 LIKE column2
  2303.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  2304.   $limits{'group_by_position'}  = 0; # Can use 'GROUP BY 1'
  2305.   $limits{'alter_table'}    = 1;
  2306.   $limits{'alter_add_multi_col'}= 0;
  2307.   $limits{'alter_table_dropcol'}= 0;
  2308.  
  2309.   $limits{'group_func_extra_std'} = 0; # Have group function std().
  2310.  
  2311.   $limits{'func_odbc_mod'}    = 1; # Have function mod.
  2312.   $limits{'func_extra_%'}    = 0; # Has % as alias for mod()
  2313.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  2314.   $limits{'func_extra_if'}    = 0; # Have function if.
  2315.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  2316.   $limits{'NEG'}        = 1; # Supports -id
  2317.   $limits{'func_extra_in_num'}    = 0; # Has function in
  2318.   return $self;
  2319. }
  2320.  
  2321. #
  2322. # Get the version number of the database
  2323. #
  2324.  
  2325. sub version
  2326. {
  2327.   my ($self)=@_;
  2328.   return "IBM DB2 5";        #DBI/ODBC can't return the server version
  2329. }
  2330.  
  2331. sub connect
  2332. {
  2333.   my ($self)=@_;
  2334.   my ($dbh);
  2335.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user, $main::opt_password) ||
  2336.     die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  2337.   return $dbh;
  2338. }
  2339.  
  2340. #
  2341. # Returns a list of statements to create a table
  2342. # The field types are in ANSI SQL format.
  2343. #
  2344.  
  2345. sub create
  2346. {
  2347.   my($self,$table_name,$fields,$index) = @_;
  2348.   my($query,@queries,$nr);
  2349.  
  2350.   $query="create table $table_name (";
  2351.   foreach $field (@$fields)
  2352.   {
  2353.     $field =~ s/mediumint/integer/i;
  2354.     $field =~ s/float\(\d+,\d+\)/float/i;
  2355.     $field =~ s/integer\(\d+\)/integer/i;
  2356.     $field =~ s/int\(\d+\)/integer/i;
  2357.     $field =~ s/tinyint\(\d+\)/smallint/i;
  2358.     $field =~ s/tinyint/smallint/i;
  2359.     $field =~ s/smallint\(\d+\)/smallint/i;
  2360.     $field =~ s/smallinteger/smallint/i;
  2361.     $field =~ s/blob/varchar(256)/i;
  2362.     $query.= $field . ',';
  2363.   }
  2364.   substr($query,-1)=")";        # Remove last ',';
  2365.   push(@queries,$query);
  2366.   $nr=0;
  2367.   foreach $index (@$index)
  2368.   {
  2369.     $ext="WITH DISALLOW NULL";
  2370.     if (($index =~ s/primary key/unique index primary_key/i))
  2371.     {
  2372.       $ext="WITH PRIMARY;"
  2373.     }
  2374.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  2375.     {
  2376.       $nr++;
  2377.       $index="unique index ${table_name}_$nr ($1)";
  2378.     }
  2379.     $index =~ /^(.*)\s+(\(.*\))$/;
  2380.     push(@queries,"create ${1} on $table_name $2");
  2381.   }
  2382.   return @queries;
  2383. }
  2384.  
  2385. #
  2386. # Do any conversions to the ANSI SQL query so that the database can handle it
  2387. #
  2388.  
  2389. sub query {
  2390.   my($self,$sql) = @_;
  2391.   return $sql;
  2392. }
  2393.  
  2394. sub drop_index
  2395. {
  2396.   my ($self,$table,$index) = @_;
  2397.   return "DROP INDEX $table.$index";
  2398. }
  2399.  
  2400. #
  2401. # Abort if the server has crashed
  2402. # return: 0 if ok
  2403. #      1 question should be retried
  2404. #
  2405.  
  2406. sub abort_if_fatal_error
  2407. {
  2408.   return 0;
  2409. }
  2410.  
  2411.  
  2412.  
  2413. 1;
  2414.